package com.roc.admin.infrastructure.common.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.roc.admin.domain.entity.LoginLog;
import com.roc.admin.domain.repository.LoginLogRepository;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;

/**
 * 登录日志切面
 */
@Aspect
@Component
public class LoginLogAspect {

    private final LoginLogRepository loginLogRepository;

    public LoginLogAspect(LoginLogRepository loginLogRepository) {
        this.loginLogRepository = loginLogRepository;
    }

    /**
     * 配置切入点
     */
    @Pointcut("execution(* com.roc.admin.interfaces.controller.UserController.login(..))")
    public void loginPointcut() {
    }

    /**
     * 处理登录成功
     *
     * @param joinPoint 切点
     * @param result    返回值
     */
    @AfterReturning(pointcut = "loginPointcut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        handleLoginLog(joinPoint, null, result);
    }

    /**
     * 处理登录失败
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "loginPointcut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        handleLoginLog(joinPoint, e, null);
    }

    /**
     * 处理登录日志
     *
     * @param joinPoint 切点
     * @param e         异常
     * @param result    返回值
     */
    private void handleLoginLog(JoinPoint joinPoint, Exception e, Object result) {
        try {
            // 获取当前请求
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                return;
            }

            HttpServletRequest request = attributes.getRequest();

            // 获取登录参数
            Object[] args = joinPoint.getArgs();
            String username = (String) args[0];

            // 创建登录日志
            LoginLog loginLog = new LoginLog();
            loginLog.setUsername(username);
            loginLog.setIp(getIpAddress(request));
            loginLog.setLocation(getLocationByIp(loginLog.getIp()));
            loginLog.setBrowser(getBrowser(request));
            loginLog.setOs(getOs(request));
            loginLog.setLoginTime(LocalDateTime.now());

            // 设置登录结果
            if (e != null) {
                loginLog.setStatus(0);
                loginLog.setMessage("登录失败：" + e.getMessage());
            } else {
                // 判断登录是否成功
                if (result != null && StpUtil.isLogin()) {
                    loginLog.setStatus(1);
                    loginLog.setMessage("登录成功");
                    loginLog.setUserId(StpUtil.getLoginIdAsLong());
                } else {
                    loginLog.setStatus(0);
                    loginLog.setMessage("登录失败：用户名或密码错误");
                }
            }

            // 保存登录日志
            loginLogRepository.save(loginLog);
        } catch (Exception ex) {
            // 记录日志失败，不影响业务
            ex.printStackTrace();
        }
    }

    /**
     * 获取IP地址
     *
     * @param request 请求
     * @return IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 根据IP获取地理位置
     *
     * @param ip IP地址
     * @return 地理位置
     */
    private String getLocationByIp(String ip) {
        // 实际项目中可以调用IP地址库或第三方API获取地理位置
        // 这里简化处理，直接返回IP
        return "未知位置(" + ip + ")";
    }

    /**
     * 获取浏览器类型
     *
     * @param request 请求
     * @return 浏览器类型
     */
    private String getBrowser(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            return "未知浏览器";
        }
        
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            return "IE浏览器";
        } else if (userAgent.contains("Firefox")) {
            return "Firefox浏览器";
        } else if (userAgent.contains("Chrome")) {
            return "Chrome浏览器";
        } else if (userAgent.contains("Safari")) {
            return "Safari浏览器";
        } else if (userAgent.contains("Opera")) {
            return "Opera浏览器";
        } else {
            return "未知浏览器";
        }
    }

    /**
     * 获取操作系统
     *
     * @param request 请求
     * @return 操作系统
     */
    private String getOs(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            return "未知操作系统";
        }
        
        if (userAgent.contains("Windows")) {
            return "Windows";
        } else if (userAgent.contains("Mac")) {
            return "Mac OS";
        } else if (userAgent.contains("Linux")) {
            return "Linux";
        } else if (userAgent.contains("Android")) {
            return "Android";
        } else if (userAgent.contains("iOS")) {
            return "iOS";
        } else {
            return "未知操作系统";
        }
    }
}
